#pragma once
#include <iostream>
#include <set>
#include <string>
#include <functional>
#include "InetAddr.hpp"
#include "ThreadPool-Singleton.hpp"
#include "LockGuard.hpp"

using task_t = std::function<void()>;

class MessageRoute
{
public:
    MessageRoute()
    {
        pthread_mutex_init(&_mutex, nullptr);
    }
    void AddUser(const InetAddr& addr)
    {
        _users.insert(addr);
    }
    void DelUser(const InetAddr& addr)
    {
        _users.erase(addr);
    }
    void RouteHelper(int fd, std::string message, InetAddr addr)
    {
        LockGuard lg(_mutex);
        std::string ret = "[" + addr.IP() + ":" + std::to_string(addr.Port()) + "]# " + message;
        for (auto& user : _users)
        {
            struct sockaddr_in peer = user.Addr();
            std::cout << user.IP() << "-" << user.Port() << std::endl;
            ::sendto(fd, ret.c_str(), ret.size(), 0, reinterpret_cast<struct sockaddr*>(&peer), sizeof(peer));
        }
    }
    void Route(int fd, std::string message, InetAddr addr)
    {
        AddUser(addr);

        if(message == "Q" || message == "QUIT")
            DelUser(addr);
        
        task_t t = std::bind(&MessageRoute::RouteHelper, this, fd, message, addr);
        ThreadPool<task_t>::GetInstance()->Enqueue(t);
    }
    ~MessageRoute()
    {
        pthread_mutex_destroy(&_mutex);
    }
private:
    std::set<InetAddr> _users;
    pthread_mutex_t _mutex;
};